/*******************************************************************************
 * Package: com.song.flowable.service.impl
 * Type:    BpmProcessDefinitionServiceImpl
 * Date:    2023-11-27 22:24
 *
 * Copyright (c) 2023 LTD All Rights Reserved.
 *
 * You may not use this file except in compliance with the License.
 *******************************************************************************/
package com.song.flowable.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.song.common.util.CommUtil;
import com.song.common.constants.CommonConstant;
import com.song.flowable.convert.ProcessDefinitionConvert;
import com.song.flowable.dto.ProcessDefinitionPageDTO;
import com.song.flowable.dto.StartFlowableDTO;
import com.song.flowable.service.ProcessDefinitionService;
import com.song.flowable.vo.ProcessDefinitionVO;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 功能描述： 流程定义
 *
 * @author Songxianyang
 * @date 2023-11-27 22:24
 */
@Service
@RequiredArgsConstructor
public class ProcessDefinitionServiceImpl implements ProcessDefinitionService {

    private final RepositoryService repositoryService;
    private final RuntimeService runtimeService;

    /**
     * 获得流程定义分页
     *
     * @param dto 分页入参
     * @return List<ProcessDefinition>
     */
    @Override
    public Page<ProcessDefinitionVO> getProcessDefinitionPage(ProcessDefinitionPageDTO dto) {
        Page<ProcessDefinitionVO> page = new Page<>();
        ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
        if (StringUtils.isNotBlank(dto.getKey())) {
            definitionQuery.processDefinitionKey(dto.getKey());
        }
        // 执行查询
        List<ProcessDefinition> processDefinitions = new ArrayList<>();
        if (Objects.nonNull(dto.getPage()) && Objects.nonNull(dto.getPageSize())) {
            processDefinitions = definitionQuery.orderByProcessDefinitionVersion().desc()
                    .listPage(dto.getPageSize() * (dto.getPage() - 1), dto.getPageSize());
        } else {
            processDefinitions = definitionQuery.orderByProcessDefinitionVersion().desc()
                    .list();
        }
        page.setTotal(definitionQuery.count());

        if (CommUtil.isEmpty(processDefinitions)) {
            page.setRecords(Collections.EMPTY_LIST);
            return page;
        }
        List<ProcessDefinitionVO> processDefinitionVOS = ProcessDefinitionConvert.INSTANCE.toConvertProcessDefinitionList(processDefinitions);
        page.setRecords(processDefinitionVOS);
        return page;
    }

    /**
     * 获得流程定义对应的 BPMN XML
     *
     * @param id 流程定义编号
     * @return BPMN XML
     */
    @Override
    public String getXML(String id) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(id);
        if (bpmnModel == null) {
            return null;
        }
        BpmnXMLConverter converter = new BpmnXMLConverter();
        return StrUtil.utf8Str(converter.convertToXML(bpmnModel));
    }

    /**
     * 启动流程
     *
     * @param dto
     * @return
     */
    @Override
    public String startFlowable(StartFlowableDTO dto) {
        // todo  流程设置发起人
        Authentication.setAuthenticatedUserId("admin");
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(dto.getProcessDefinitionKey(),
                dto.getMap());
        return "启动流程成功，流程实例ID为：" + processInstance.getId();
    }

    /**
     * 查询所有启动的流程列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<Execution> executions(StartFlowableDTO dto) {
        //分页
        if (Objects.nonNull(dto.getPage()) || Objects.nonNull(dto.getPageSize())) {
            List<Execution> executionPages = runtimeService.createExecutionQuery().processDefinitionKey(dto.getProcessDefinitionKey())
                    .listPage(dto.getPage(), dto.getPageSize());
            return executionPages;
        }
        //不分页
        List<Execution> executions = runtimeService.createExecutionQuery().processDefinitionKey(dto.getProcessDefinitionKey()).list();
        return executions;
    }

    /**
     * 挂起流程定义(停止、暂停）或（唤醒、激活）被挂起的流程定义
     *
     * @param definitionId
     * @param state
     * @return
     */
    @Override
    public Boolean stopOrActivate(String definitionId, String state) {
        //激活
        if (CommUtil.equals(CommonConstant.one, state)) {
            repositoryService.activateProcessDefinitionById(definitionId);
        }
        // 挂起
        if (CommUtil.equals(CommonConstant.two, state)) {
            repositoryService.suspendProcessDefinitionById(definitionId);
        }
        return Boolean.TRUE;
    }
}
